#ifndef __ONLINE_USER__
#define __ONLINE_USER__

#include "CTHashObjectMgr.h"
#include "CTMsgBase.h"
#include "CTSizeString.h"
#include "CTKeyValue.h"

class CPlatformInfo
{
public:
    CPlatformInfo()
        : _bIsTencentLogin(false)
    {
        
    }

    bool _bIsTencentLogin;        
    CTKeyValue _stTencentApiKeyValue;
    int _iLastCheckLoginTime;       //上次保活时间
};

class CMainCtrl;
class CPlayerOnline
{
public:
    CPlayerOnline()
    {}
    virtual ~CPlayerOnline(){}

    friend class CMainCtrl;

    size_t CountSize(int iMaxPlayerOnline)
    {
        m_iMaxPlayerOnline = iMaxPlayerOnline;
        return m_stOnlineHash.CountSize(iMaxPlayerOnline);
    }

    int Init(const char* sBuf, bool bIsResetShm)
    {
        return m_stOnlineHash.Init(sBuf, m_iMaxPlayerOnline, 2, 2, bIsResetShm);
    }

    /**
    * 检查用户是否在线.
    * @param[in] iUin 
    * @return 在线状态
    */
    bool CheckOnline(unsigned int uiGID)
    {
        int iIndex = m_stOnlineHash.HashFind(uiGID);
        if (iIndex < 0)
        {
            return false;
        }

        return true;
    }

    /**
    * 将用户设置为在线状态.
    */
    int SetOnline(unsigned int uiGID, CEnpNetHead& stHead, int iNow, CPlatformInfo& stPlatformInfo)
    {
        int iIndex = m_stOnlineHash.HashFind(uiGID);
        if (iIndex >= 0)
        {
            if (stHead.uiHandle == m_stOnlineHash[iIndex].uiHandle)  //是同一个连接发起的    
            {
                CT_WARNING(("invalid setonline , user is online, GID = %u", uiGID));
                return 0;                                           //表示重复设置
            }
            else
            {
                SetOffline(uiGID, m_stOnlineHash[iIndex].uiHandle);
            }
        }

        iIndex = m_stOnlineHash.HashAlloc(uiGID);
        if (iIndex < 0)
        {
            return -1;
        }

        stHead.uiAct1 = uiGID;
        m_stOnlineHash[iIndex].iLoginTime = iNow;
        m_stOnlineHash[iIndex].uiGID = uiGID;
        m_stOnlineHash[iIndex].uiRemoteIP = stHead.uiRemoteIP;
        m_stOnlineHash[iIndex].unRemotePort = stHead.unRemotePort;
        m_stOnlineHash[iIndex].uiLocalIP = stHead.uiLocalIP;
        m_stOnlineHash[iIndex].unLocalPort = stHead.unLocalPort;
        m_stOnlineHash[iIndex].uiHandle = stHead.uiHandle;
        m_stOnlineHash[iIndex].ucEnodeMethod = stHead.ucEnodeMethod;
        m_stOnlineHash[iIndex].stPlatformInfo = stPlatformInfo;

        GetAllOnlineUser(m_astAllOnlineGID);

        return 0;
    }

    int GetUserLoginTime(unsigned int uiGID, int& iLoginTime)
    {
        int iIndex = m_stOnlineHash.HashFind(uiGID);
        if (iIndex < 0)
        {
            iLoginTime = 0;
            return -1;
        }

        iLoginTime = m_stOnlineHash[iIndex].iLoginTime;
        return 0;
    }

    int SetUserLoginTime(unsigned int uiGID, int iLoginTime)
    {
        int iIndex = m_stOnlineHash.HashFind(uiGID);
        if (iIndex < 0)
        {
            iLoginTime = 0;
            return -1;
        }

        m_stOnlineHash[iIndex].iLoginTime = iLoginTime;
        return 0;
    }

    int GetUserOnlineTime(unsigned int uiGID, int iNow, int& iOnlineTime)
    {
        int iIndex = m_stOnlineHash.HashFind(uiGID);
        if (iIndex < 0)
        {
            iOnlineTime = 0;
            return -1;
        }

        iOnlineTime = iNow - m_stOnlineHash[iIndex].iLoginTime;
        return 0;
    }

    int SetOffline(unsigned int uiGID, unsigned int uiHandle)
    {
        int iIndex = m_stOnlineHash.HashFind(uiGID);
        if (iIndex < 0)
        {
            return 0;
        }

        if (m_stOnlineHash[iIndex].uiHandle != uiHandle) //防止踢出后登录的用户（有这种情况：用户重复登录->踢出旧用户->新用户登录->旧用户断线(SetOffline)）
        {
            return -1;
        }

        m_stOnlineHash.HashFreeByIndex(iIndex);

        GetAllOnlineUser(m_astAllOnlineGID);

        return 0;
    }

    /**
    * 获取在线用户的CEnpNetHead.
    * @param[in] iUin 
    * @param[out] stHead 
    * @return 正常返回0，否则返回错误码
    */
    int GetOnlinePlayerHandle(unsigned int uiGID, CEnpNetHead& stHead)
    {
        if (CheckOnline(uiGID) == false)
        {
            return -1;
        }

        int iIndex = m_stOnlineHash.HashFind(uiGID);
        if (iIndex < 0)
        {
            return -1;
        }

        stHead.uiRemoteIP = m_stOnlineHash[iIndex].uiRemoteIP;
        stHead.unRemotePort = m_stOnlineHash[iIndex].unRemotePort;
        stHead.uiLocalIP = m_stOnlineHash[iIndex].uiLocalIP;
        stHead.unLocalPort = m_stOnlineHash[iIndex].unLocalPort;
        stHead.uiHandle = m_stOnlineHash[iIndex].uiHandle;
        stHead.ucEnodeMethod = m_stOnlineHash[iIndex].ucEnodeMethod;
        stHead.uiAct1 = uiGID;
        
        return 0;
    }

    int GetOnlinePlayerPlatformInfo(unsigned int uiGID, CPlatformInfo& stPlatformInfo)
    {
        if (CheckOnline(uiGID) == false)
        {
            return -1;
        }

        int iIndex = m_stOnlineHash.HashFind(uiGID);
        if (iIndex < 0)
        {
            return -1;
        }

        stPlatformInfo = m_stOnlineHash[iIndex].stPlatformInfo;

        return 0;
    }

    int SetOnlinePlayerPlatformInfo(unsigned int uiGID, CPlatformInfo& stPlatformInfo)
    {
        if (CheckOnline(uiGID) == false)
        {
            return -1;
        }

        int iIndex = m_stOnlineHash.HashFind(uiGID);
        if (iIndex < 0)
        {
            return -1;
        }

        m_stOnlineHash[iIndex].stPlatformInfo = stPlatformInfo;

        return 0;
    }

    /**
    * 获取在线用户数量.
    * @return 正常返回大于0
    */
    int GetOnlineCount()
    {
        return m_stOnlineHash.Size(1);
    }

    //获取所有在线用户
    void  GetAllOnlineUser(CTArray<unsigned int, MAX_PLAYER_ONLINE>& astGIDArray)
    {
        astGIDArray.m_iUsedCount = 0;
        int iIndex = m_stOnlineHash.GetHeadIndex();
        while(iIndex>=0)
        {
            astGIDArray[astGIDArray.m_iUsedCount++] = m_stOnlineHash[iIndex].uiGID;
            iIndex = m_stOnlineHash.GetNextIndex(iIndex);
        }
    }

    const CTArray<unsigned int, MAX_PLAYER_ONLINE>& GetAllOnlineUser()
    {
        return m_astAllOnlineGID;
    }

    const char* GetStatInfo()
    {
        m_stStatInfo.Set("\n ------ online user ------ \n");
        for (int iIndex = m_stOnlineHash.GetHeadIndex(); iIndex>=0; iIndex = m_stOnlineHash.GetNextIndex(iIndex))
        {
            m_stStatInfo.Cat("GID = %u, last login = %d\n", 
                        m_stOnlineHash.GetKeyByIndex(iIndex), m_stOnlineHash[iIndex].iLoginTime);
        }

        return m_stStatInfo.Get();
    }
private:

    typedef struct ONLINE_STAT 
    {
        unsigned int uiGID;       
        int iLoginTime;                     ///< 登录时间
        unsigned int		uiRemoteIP;     ///< 远程客户端的IP
        unsigned short		unRemotePort;   ///< 远程客户端的端口
        unsigned int		uiLocalIP;		///< 服务器端IP
        unsigned short		unLocalPort;	///< 服务器端端口
        unsigned int		uiHandle;		///< 本连接对应的ENP Handle(上层程序不要修改)
        unsigned char       ucEnodeMethod;  ///< 编码方式
        CPlatformInfo       stPlatformInfo;  //平台信息
    }ONLINE_STAT;

    int m_iMaxPlayerOnline;
    CTHashObjectMgr<int, ONLINE_STAT> m_stOnlineHash;

    CTSizeString<2048> m_stStatInfo;
    CTArray<unsigned int, MAX_PLAYER_ONLINE> m_astAllOnlineGID;

};

#endif

